#include "IceLuaSupport.h"
#include "Ice/Ice.h"
#include "CCIceSession.h"
#include "LuaHandlerIce.h"

class LuaExceptionFactory : public ::IceInternal::UserExceptionFactory
{
public:
    virtual void createAndThrow(const std::string& _typeId)
    {
        throw LuaException(_typeId);
    }
};

IceInternal::UserExceptionFactoryPtr lua_Exception_Factory = new LuaExceptionFactory();

///////////////////////////////////////////////////////////////


AMI_Object_ice_invoke_lua::AMI_Object_ice_invoke_lua(int callback, Ice::ObjectPrx prx)
	:_callback(callback), _proxy(prx)
{
}

void AMI_Object_ice_invoke_lua::exception(const ::Ice::Exception& ex)
{
	_callback.invoke<const std::string&,const Ice::Exception*>("exception", &ex);
}

IceInternal::CallbackBasePtr AMI_Object_ice_invoke_lua::__verify(::Ice::LocalObjectPtr& cookie)
{
	if(cookie != 0) // Makes sure begin_ was called without a cookie
	{
		throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "cookie specified for callback without cookie");
	}
	return this;
}

void AMI_Object_ice_invoke_lua::__sent(const ::Ice::AsyncResultPtr& result) const
{
	result->sentSynchronously();
}

bool AMI_Object_ice_invoke_lua::__hasSentCallback() const
{
	return false;
}

void AMI_Object_ice_invoke_lua::__completed(const ::Ice::AsyncResultPtr& __result) const
{
	bool __ok;
	try
	{
		__ok = __result->__wait();
	}
	catch(const ::Ice::Exception& ex)
	{
		const_cast<AMI_Object_ice_invoke_lua*>(this)->_callback.invoke<const std::string&,const Ice::Exception*>("exception", &ex);
		return;
	}

	if (!__ok)
	{
		try {
			IceInternal::BasicStream* _is = __result->__startReadParams();
			_is->throwException(lua_Exception_Factory);
		} catch (const LuaException& e) {
			const_cast<AMI_Object_ice_invoke_lua*>(this)->_callback.invoke<const std::string&, const LuaException*>("exception", &e);
			__result->__endReadParams();
		}
	}
	else
	{
		IceInternal::BasicStream* _is = __result->__startReadParams();

		InputStreamWrapper stream(_is);
		const_cast<AMI_Object_ice_invoke_lua*>(this)->_callback.invoke<const std::string&, InputStreamWrapper*>("response", &stream);
		__result->__endReadParams();
	}
}

////////////////////////////////////////////////////////////////////////////////////////

CallbackI::CallbackI( int lunFunc )
	:_luaHandler(lunFunc)
{
}

CallbackI::~CallbackI()
{
}

Ice::DispatchStatus CallbackI::__dispatch( IceInternal::Incoming& in, const Ice::Current& current)
{
	std::vector<Ice::Byte> data;
	::IceInternal::BasicStream* __is = in.startReadParams();

	InputStreamWrapper stream = InputStreamWrapper(__is);

	_luaHandler.invoke< const ::std::string&,const ::std::string& , InputStreamWrapper*>(current.facet,current.operation, &stream);

	in.endReadParams();

	return Ice::DispatchOK;
}
